package cn.wolfcode.business.service.impl;

import cn.wolfcode.business.domain.BusBpmnInfo;
import cn.wolfcode.business.domain.BusCarPackageAudit;
import cn.wolfcode.business.domain.BusServiceItem;
import cn.wolfcode.business.domain.vo.AuditInfoVo;
import cn.wolfcode.business.domain.vo.AuditVo;
import cn.wolfcode.business.mapper.BusServiceItemMapper;
import cn.wolfcode.business.service.IBusBpmnInfoService;
import cn.wolfcode.business.service.IBusCarPackageAuditService;
import cn.wolfcode.business.service.IBusServiceItemService;
import cn.wolfcode.common.core.domain.entity.SysUser;
import cn.wolfcode.common.utils.DateUtils;
import cn.wolfcode.common.utils.SecurityUtils;
import cn.wolfcode.system.service.ISysConfigService;
import cn.wolfcode.system.service.ISysUserService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 服务项Service业务层处理
 * 
 * @author wolfcode
 * @date 2025-08-20
 */
@Service
public class BusServiceItemServiceImpl implements IBusServiceItemService 
{
    @Autowired
    private BusServiceItemMapper busServiceItemMapper;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysConfigService sysConfigService;
    @Autowired
    private IBusCarPackageAuditService busCarPackageAuditService;
    @Autowired
    private IBusBpmnInfoService busBpmnInfoService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;

    /**
     * 查询服务项
     * 
     * @param id 服务项主键
     * @return 服务项
     */
    @Override
    public BusServiceItem selectBusServiceItemById(Long id)
    {
        return busServiceItemMapper.selectBusServiceItemById(id);
    }

    /**
     * 查询服务项列表
     * 
     * @param busServiceItem 服务项
     * @return 服务项
     */
    @Override
    public List<BusServiceItem> selectBusServiceItemList(BusServiceItem busServiceItem)
    {
        return busServiceItemMapper.selectBusServiceItemList(busServiceItem);
    }

    /**
     * 新增服务项
     * 
     * @param busServiceItem 服务项
     * @return 结果
     */
    @Override
    public int insertBusServiceItem(BusServiceItem busServiceItem)
    {
        // 参数合理化校验
        if (busServiceItem == null) {
            throw new RuntimeException("非法参数");
        }
        // 前端校验的后端都要校验
        if(busServiceItem.getName() == null || busServiceItem.getOriginalPrice()==null
            || busServiceItem.getDiscountPrice() == null || busServiceItem.getCarPackage()==null
            || busServiceItem.getServiceCatalog() == null || busServiceItem.getInfo() == null){
            throw new RuntimeException("非法参数");
        }
        // 价格校验
        // 对于 BigDecimal 类型比较需要使用 比较者.compareTo(被比较者)
        // 得到的结果  正数（比较者大）   0（一样大）    负数（被比较者大）
        if(busServiceItem.getOriginalPrice().compareTo(new BigDecimal(0)) < 0    // 原价 < 0
            || busServiceItem.getDiscountPrice().compareTo(new BigDecimal(0)) < 0  // 折扣价 < 0
            || busServiceItem.getOriginalPrice().compareTo(busServiceItem.getDiscountPrice()) < 0){ // 原价 < 折扣价
            throw new RuntimeException("原价或折扣价必须大于0 且 原价不能低于折扣价");
        }
        // 判断是否为套餐
        if(BusServiceItem.CARPACKAGE_NO.equals(busServiceItem.getCarPackage())){
            // 不是套餐则将状态设置为 无需审核(4)
            busServiceItem.setAuditStatus(BusServiceItem.AUDITSTATUS_NO_REQUIRED);
        } else {
            // 是套餐则将状态设置为 初始化(0)
            busServiceItem.setAuditStatus(BusServiceItem.AUDITSTATUS_INIT);
        }
        // 安全性设置，新增的记录默认为下架状态
        busServiceItem.setSaleStatus(BusServiceItem.SALESTATUS_OFF);
        busServiceItem.setCreateTime(DateUtils.getNowDate());
        return busServiceItemMapper.insertBusServiceItem(busServiceItem);
    }

    /**
     * 修改服务项
     * 
     * @param busServiceItem 服务项
     * @return 结果
     */
    @Override
    public int updateBusServiceItem(BusServiceItem busServiceItem)
    {
        // 参数合理化校验
        if (busServiceItem == null) {
            throw new RuntimeException("非法参数");
        }
        // 前端校验的后端都要校验
        if(busServiceItem.getName() == null || busServiceItem.getOriginalPrice()==null
                || busServiceItem.getDiscountPrice() == null || busServiceItem.getCarPackage()==null
                || busServiceItem.getServiceCatalog() == null || busServiceItem.getInfo() == null){
            throw new RuntimeException("非法参数");
        }
        // 价格校验
        // 对于 BigDecimal 类型比较需要使用 比较者.compareTo(被比较者)
        // 得到的结果  正数（比较者大）   0（一样大）    负数（被比较者大）
        if(busServiceItem.getOriginalPrice().compareTo(new BigDecimal(0)) < 0    // 原价 < 0
                || busServiceItem.getDiscountPrice().compareTo(new BigDecimal(0)) < 0  // 折扣价 < 0
                || busServiceItem.getOriginalPrice().compareTo(busServiceItem.getDiscountPrice()) < 0){ // 原价 < 折扣价
            throw new RuntimeException("原价或折扣价必须大于0 且 原价不能低于折扣价");
        }
        // 是否套餐不让修改
        // 由于是否套餐是禁止修改的，所以我们不能用前端传递的数据进行判定。因为有可能被人通过特殊手段将当前字段修改过。
        BusServiceItem oldObj = this.selectBusServiceItemById(busServiceItem.getId());
        if (oldObj == null) {
            throw new RuntimeException("非法参数");
        }
        if(!oldObj.getCarPackage().equals(busServiceItem.getCarPackage())){
            throw new RuntimeException("是否套餐禁止修改");
        }
        // 上架中的商品禁止修改
        // 数据库中存储的是 name=xx&&originalPrice=xx&&discountPrice=xx&&saleStatus=0
        // localhost/business/serviceItem?name=xx&&originalPrice=xx&&discountPrice=0&&saleStatus=1
        // 用户非法修改了上下架状态
        if(!oldObj.getSaleStatus().equals(busServiceItem.getSaleStatus())){
            throw new RuntimeException("非法参数");
        }
        if(BusServiceItem.SALESTATUS_ON.equals(oldObj.getSaleStatus())){
            throw new RuntimeException("上架中的商品禁止修改");
        }
        // 是套餐且状态为审批中的禁止修改
        // 用户非法修改了审批状态
        if(!oldObj.getAuditStatus().equals(busServiceItem.getAuditStatus())){
            throw new RuntimeException("非法参数");
        }
        if(BusServiceItem.CARPACKAGE_YES.equals(oldObj.getCarPackage())
        && BusServiceItem.AUDITSTATUS_AUDITING.equals(oldObj.getAuditStatus())){
            throw new RuntimeException("审批中的服务项禁止修改");
        }
        // 若状态是审批通过或审批拒绝则需要将其状态修改为初始化
        if(BusServiceItem.AUDITSTATUS_APPROVED.equals(oldObj.getAuditStatus())
            || BusServiceItem.AUDITSTATUS_REPLY.equals(oldObj.getAuditStatus())){
            busServiceItem.setAuditStatus(BusServiceItem.AUDITSTATUS_INIT);
        }
        return busServiceItemMapper.updateBusServiceItem(busServiceItem);
    }

    /**
     * 批量删除服务项
     * 
     * @param ids 需要删除的服务项主键
     * @return 结果
     */
    @Override
    public int deleteBusServiceItemByIds(Long[] ids)
    {
        // 参数合理化校验
        if(ids == null || ids.length == 0){
            throw new RuntimeException("非法参数");
        }
        // 因为不存在批量删除，所以我们可以直接获取到 id
        Long id = ids[0];
        BusServiceItem busServiceItem = this.selectBusServiceItemById(id);
        if(busServiceItem == null){
            throw new RuntimeException("非法参数");
        }
        // 上架中的商品禁止删除
        if(BusServiceItem.SALESTATUS_ON.equals(busServiceItem.getSaleStatus())){
            throw new RuntimeException("上架中的商品禁止删除");
        }
        // 不是套餐可以直接删除。是套餐 且 状态是审批中 ==> 禁止删除
        if(BusServiceItem.CARPACKAGE_YES.equals(busServiceItem.getCarPackage()) // 是套餐
            && BusServiceItem.AUDITSTATUS_AUDITING.equals(busServiceItem.getAuditStatus())){ // 状态是审批中
            throw new RuntimeException("审批中的商品禁止删除");
        }

        return busServiceItemMapper.deleteBusServiceItemByIds(ids);
    }

    /**
     * 删除服务项信息
     * 
     * @param id 服务项主键
     * @return 结果
     */
    @Override
    public int deleteBusServiceItemById(Long id)
    {
        return busServiceItemMapper.deleteBusServiceItemById(id);
    }

    /**
     * 上架服务项
     */
    @Override
    public int saleOn(Long id) {
        // 参数合理化验证
        if(id == null){
            throw new RuntimeException("非法参数");
        }
        // 根据参数查询出原始对象
        BusServiceItem busServiceItem = this.selectBusServiceItemById(id);
        if(busServiceItem == null){
            throw new RuntimeException("非法参数");
        }
        // 必须是下架状态的服务项才可以进行上架操作。
        if(BusServiceItem.SALESTATUS_ON.equals(busServiceItem.getSaleStatus())){
            throw new RuntimeException("该服务项已上架，请勿重复上架");
        }
        // 是套餐 状态必须是 审批通过 才可以进行上架操作
        if(BusServiceItem.CARPACKAGE_YES.equals(busServiceItem.getCarPackage()) // 是套餐
        && !BusServiceItem.AUDITSTATUS_APPROVED.equals(busServiceItem.getAuditStatus())){ // && 不是审批通过
            throw new RuntimeException("该服务项必须要审批通过后才可以进行上架操作");
        }
        return busServiceItemMapper.changeSlaeStatus(id,BusServiceItem.SALESTATUS_ON);
    }

    /**
     * 下架服务项
     */
    @Override
    public int saleOff(Long id) {
        // 参数合理化验证
        if(id == null){
            throw new RuntimeException("非法参数");
        }
        // 根据参数查询出原始对象
        BusServiceItem busServiceItem = this.selectBusServiceItemById(id);
        if(busServiceItem == null){
            throw new RuntimeException("非法参数");
        }
        // 必须是上架状态的服务项才可以进行下架操作。
        if(BusServiceItem.SALESTATUS_OFF.equals(busServiceItem.getSaleStatus())){
            throw new RuntimeException("该服务项已下架，请勿重复下架");
        }
        return busServiceItemMapper.changeSlaeStatus(id,BusServiceItem.SALESTATUS_OFF);
    }

    /**
     * 准备发起审批数据  服务项、店长集合、财务集合、阈值
     * @param id 服务项id
     * @return 发起审批数据
     */
    @Override
    public AuditInfoVo getAuditInfo(Long id) {
        // 参数合理化验证
        if(id == null){
            throw new RuntimeException("非法参数");
        }
        BusServiceItem busServiceItem = this.selectBusServiceItemById(id);
        if(busServiceItem == null){
            throw new RuntimeException("非法参数");
        }
        AuditInfoVo vo = new AuditInfoVo();
        // 准备服务项数据
        vo.setBusServiceItem(busServiceItem);
        // 准备店长数据
        List<SysUser> shopOwnerList = userService.selectUserByRoleKey("shopOwner");
        vo.setShopOwnerList(shopOwnerList);
        // 准备阈值
        String discountPriceLimit = sysConfigService.selectConfigByKey("discountPriceLimit");
        vo.setDiscountPriceLimit(new BigDecimal(discountPriceLimit));
        // 对比服务项的折扣价若 >= 阈值 则需要财务审批
        if(busServiceItem.getDiscountPrice().compareTo(new BigDecimal(discountPriceLimit)) >= 0){
            // 准备财务数据
            List<SysUser> financeList = userService.selectUserByRoleKey("finance");
            vo.setFinanceList(financeList);
        }
        return vo;
    }

    /**
     * 发起审批
     * @param vo 服务项id,所选店长 id、财务 id、信息 info
     * @return 成功 || 失败
     */
    @Override
    @Transactional
    public int audit(AuditVo vo) {
        // 参数合理化校验
        if(vo == null || vo.getServiceItemId() == null
                || vo.getShopOwnerId() == null || vo.getInfo() == null)
        {
            throw new RuntimeException("非法参数");
        }
        // 根据服务项 id 查询出服务项对象
        BusServiceItem busServiceItem = this.selectBusServiceItemById(vo.getServiceItemId());
        if(busServiceItem == null){
            throw new RuntimeException("非法参数");
        }
        // 验证状态
        //  - 必须是下架状态。
        if(BusServiceItem.SALESTATUS_ON.equals(busServiceItem.getSaleStatus())){
            throw new RuntimeException("已上架的服务项禁止发起审批");
        }
        // - 是套餐。
        if(BusServiceItem.CARPACKAGE_NO.equals(busServiceItem.getCarPackage())){
            throw new RuntimeException("非套餐禁止发起审批");
        }
        // - 处于初始化状态。
        if(!BusServiceItem.AUDITSTATUS_INIT.equals(busServiceItem.getAuditStatus())){
            throw new RuntimeException("套餐状态必须是初始化才可以进行审批");
        }
        // 封装我们的业务数据（快照表的数据）
        BusCarPackageAudit busCarPackageAudit = new BusCarPackageAudit();
        busCarPackageAudit.setServiceItemId(busServiceItem.getId());    // 服务项 id
        busCarPackageAudit.setServiceItemName(busServiceItem.getName());  // 服务项名称
        busCarPackageAudit.setServiceItemInfo(busServiceItem.getInfo());  // 服务项备注
        busCarPackageAudit.setServiceItemPrice(busServiceItem.getDiscountPrice());  // 服务项折扣价
        // busCarPackageAudit.setInstanceId();
        busCarPackageAudit.setCreatorId(SecurityUtils.getUserId().toString());  // 创建者
        busCarPackageAudit.setInfo(vo.getInfo());   // 审批备注
        busCarPackageAudit.setStatus(BusCarPackageAudit.STATUS_IN_PROGRESS);    // 状态默认审批中
        // 将封装后的数据插入到快照表中
        busCarPackageAuditService.insertBusCarPackageAudit(busCarPackageAudit);
        // 插入后会拿到我们的回填 id
        // 我们需要获取 bpmnINfo 对象中的 --> key + version.
        // 因为我们这个固定是套餐审批，所以在实体类中我们设计了一个  FLOW_AUDIT_TYPE = 0;//服务套餐审核类型
        BusBpmnInfo bpmnInfo = busBpmnInfoService.selectBpmnInfoByType(BusCarPackageAudit.FLOW_AUDIT_TYPE);
        // 查询对应的流程实例对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(bpmnInfo.getProcessDefinitionKey())
                .processDefinitionVersion(bpmnInfo.getVersion())
                .singleResult();
        // 启动实例之前我们需要封装参数 (店长和财务)
        Map<String,Object> params = new HashMap<>();
        params.put("shopOwnerId",vo.getShopOwnerId());
        // 获取阈值
        BigDecimal discountPriceLimit = new BigDecimal(sysConfigService.selectConfigByKey("discountPriceLimit"));
        // 若折扣价 》= 阈值 且传递了财务
        if(busServiceItem.getDiscountPrice().compareTo(discountPriceLimit) >= 0 && vo.getFinanceId() != null){
            params.put("financeId",vo.getFinanceId());
        }
        // 根据上面查询到的流程定义对象的 id 启动流程实例
        ProcessInstance processInstance = runtimeService.
                startProcessInstanceById(processDefinition.getId(), busCarPackageAudit.getId().toString(), params);
        // 通过上面启动后的流程实例对象获取到流程实例 id
        String processInstanceId = processInstance.getId();
        // 将获取到的 processInstanceId 更新到快照表中
        busCarPackageAuditService.updateInstanceIdById(busCarPackageAudit.getId(),processInstanceId);
        // 更新服务项表中的状态
        return busServiceItemMapper.changeAuditStatus(vo.getServiceItemId(),BusServiceItem.AUDITSTATUS_AUDITING);
    }

    /**
     * 根据服务项 id 修改服务项审批状态
     * @param id 服务项 id
     * @param auditStatus 审批状态
     * @return 成功 || 失败
     */
    @Override
    public int changeAuditStatus(Long id, Integer auditStatus) {
        return busServiceItemMapper.changeAuditStatus(id,auditStatus);
    }
}
